package com.app.business.service;

import com.app.business.model.Contract;
import com.app.business.model.OverAreaScPrice;
import com.app.business.model.OverAreaScPrice;
import com.app.system.jpa.JpaBaseDao;
import com.app.system.utils.CollectionUtils;
import com.app.system.utils.dataType.BigDecimalUtils;
import com.app.system.utils.dataType.IntegerUtils;
import com.app.system.utils.exception.Precondition;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;

/**
 * 商场超出面积单价配置
 * Created by szy on 2024/10/10
 */
@SuppressWarnings(value = "ALL")
@Service
@Transactional
public class OverAreaScPriceService extends JpaBaseDao<OverAreaScPrice,Integer> {
    @Autowired
    private ContractService contractService;

    /**
     * 删除某参数配置下所有的面积区间配置数据
     *
     * @param zsProjectId
     */
    public synchronized void deleteOverAreaScPriceByParameterId(Integer parameterId) {
        String sql = "delete from over_area_sc_price where parameter_id = :parameterId";
        this.entityManager.createNativeQuery(sql).setParameter("parameterId", parameterId).executeUpdate();
    }

    /**
     * 通过参数配置得到下面所有的面积区间分配
     *
     * @return
     */
    public List<OverAreaScPrice> getOverAreaScPriceListByParameterId(Integer parameterId) {
        //查询语句
        StringBuffer hql = new StringBuffer("from OverAreaScPrice oap where oap.parameter.id =:parameterId order by oap.sortNum,oap.id");
        Map map = Maps.newHashMap();
        map.put("parameterId", parameterId);
        return this.findHql(hql.toString(), map);
    }

    /**
     * 通过参数配置得到下面所有的面积区间分配 回购
     *
     * @return
     */
    public List<OverAreaScPrice> getOverAreaScPriceListByParameterIdForLess(Integer parameterId) {
        //查询语句
        StringBuffer hql = new StringBuffer("from OverAreaScPrice oap where oap.parameter.id =:parameterId and oap.sortNum <0 order by oap.sortNum desc,oap.id");
        Map map = Maps.newHashMap();
        map.put("parameterId", parameterId);
        return this.findHql(hql.toString(), map);
    }

    /**
     * 通过参数配置得到下面所有的面积区间分配  扩购
     *
     * @return
     */
    public List<OverAreaScPrice> getOverAreaScPriceListByParameterIdForMore(Integer parameterId) {
        //查询语句
        StringBuffer hql = new StringBuffer("from OverAreaScPrice oap where oap.parameter.id =:parameterId and oap.sortNum >0 order by oap.sortNum,oap.id");
        Map map = Maps.newHashMap();
        map.put("parameterId", parameterId);
        return this.findHql(hql.toString(), map);
    }


    /**
     * 获取某个协议下扩购面积各区间扩购面积及购房款
     *
     * @param contractId
     * @return
     */
    public Map<String, Map> getOverHouseMoneyMapForMore(Contract contract) {
        Map<String, Map> resultMap = Maps.newLinkedHashMap();
        if (contract == null || contract.getParameter() == null) {
            return resultMap;
        }
        List<OverAreaScPrice> OverAreaScPriceList = this.getOverAreaScPriceListByParameterIdForMore(contract.getParameter().getId());
        if (CollectionUtils.isNotEmpty(OverAreaScPriceList)) {
            //选房超出面积，先取出选房超出的面积
            BigDecimal zzResultArea = BigDecimalUtils.getNotNull(contract.getSyXzlAzSyArea());
            //定义每一个面积段的最小、最大、差值（最大-最小）
            BigDecimal minArea = BigDecimal.ZERO, maxArea = BigDecimal.ZERO, itemSubArea = BigDecimal.ZERO;
            //定义面积段的长度
            int overAreaPriceListLength = OverAreaScPriceList.size();

            // 创建NumberFormat对象
            NumberFormat nf = NumberFormat.getInstance();
            // 设置最大小数位数为20，这样可以确保不会截断有效的小数位
            nf.setMaximumFractionDigits(20);
            // 设置最小小数位数为0，以移除无用的0
            nf.setMinimumFractionDigits(0);
            // 设置是否使用组分隔符，如逗号
            nf.setGroupingUsed(false);

            //循环每一个面积段
            for (int i = 0; i < overAreaPriceListLength; i++) {
                //取出面积段bean
                OverAreaScPrice overAreaPrice = OverAreaScPriceList.get(i);
                //最小面积
                minArea = BigDecimalUtils.getNotNull(overAreaPrice.getMinArea());
                //最大面积
                maxArea = BigDecimalUtils.getNotNull(overAreaPrice.getMaxArea());
                //区间面积的差值
                itemSubArea = BigDecimalUtils.getBigAndBigSub(maxArea, minArea);
                //定义面积段的key值：（在财务表中也会显示）
                String areaKey = nf.format(overAreaPrice.getMaxArea()) + "m²以内(含" +  nf.format(overAreaPrice.getMaxArea()) + "m²"   +")";
                //如果是最后一个面积段，key值为:  面积（以上）
                if (i == overAreaPriceListLength - 1) {
                    areaKey = nf.format(overAreaPrice.getMinArea()) + "m²以上";
                }
                //定义本次面积段超出的面积以及需要花费的购房款
                BigDecimal itemAreaValue = BigDecimal.ZERO, itemMoneyValue = BigDecimal.ZERO;
                Map itemMap = Maps.newLinkedHashMap();

                //选房面积超出限量面积才去进行计算，没超出的话，全是""（后来添加，用来处理财务结算表显示问题）
                if (contract.getZzResultArea() != null && contract.getZzResultArea().compareTo(BigDecimal.ZERO) > 0 && contract.getZzResultAreaStatus() != null && contract.getZzResultAreaStatus() == 1) {
                    if (zzResultArea.compareTo(itemSubArea) <= 0) {
                        //如果当前选房超出面积 <= 该区间面积的差值，直接将当前超出的面积赋给本区间的面积即可
                        itemAreaValue = zzResultArea;
                        //计算需要花费的购房款（为负数：被征收人应缴纳金额）
                        itemMoneyValue = BigDecimalUtils.getBigAndBigMul(itemAreaValue, overAreaPrice.getPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
                        zzResultArea = BigDecimal.ZERO;   //该循环后，超出面积为0了
                    } else {
                        //否则，本段超出面积为：最大面积 - 最小面积
                        itemAreaValue = BigDecimalUtils.getBigAndBigSub(maxArea, minArea);
                        //计算需要花费的购房款（为负数：被征收人应缴纳金额）
                        itemMoneyValue = BigDecimalUtils.getBigAndBigMul(itemAreaValue, overAreaPrice.getPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
                        zzResultArea = BigDecimalUtils.getBigAndBigSub(zzResultArea, itemSubArea);   //该循环后超出面积应把此区间内的面积差减去，为当前还剩余超出的面积
                    }
                }

                itemMap.put("area", BigDecimalUtils.getNotNullStr(itemAreaValue));
                itemMap.put("price", BigDecimalUtils.getNotNullStr(overAreaPrice.getPrice()));
                itemMap.put("money", BigDecimalUtils.getNotNullStr(itemMoneyValue));
                resultMap.put(areaKey, itemMap);
            }
        }
        return resultMap;
    }

    /**
     * 获取某个协议下扩购面积各区间扩购面积及购房款
     *
     * @param contractId
     * @return
     */
    public Map<String, Map> getOverHouseMoneyMapForLess(Contract contract) {
        Map<String, Map> resultMap = Maps.newLinkedHashMap();
        if (contract == null || contract.getParameter() == null) {
            return resultMap;
        }
        List<OverAreaScPrice> OverAreaScPriceList = this.getOverAreaScPriceListByParameterIdForLess(contract.getParameter().getId());
        if (CollectionUtils.isNotEmpty(OverAreaScPriceList)) {
            //选房回购面积，先得到回购的面积的绝对值
            BigDecimal zzResultArea = BigDecimalUtils.getAbsolute(contract.getZzResultArea());
            //定义每一个面积段的最小、最大、差值（最大-最小）
            BigDecimal minArea = BigDecimal.ZERO, maxArea = BigDecimal.ZERO, itemSubArea = BigDecimal.ZERO;
            //定义面积段的长度
            int overAreaPriceListLength = OverAreaScPriceList.size();
            //循环每一个面积段
            for (int i = 0; i < overAreaPriceListLength; i++) {
                //取出面积段bean
                OverAreaScPrice overAreaPrice = OverAreaScPriceList.get(i);
                //最小面积
                minArea = BigDecimalUtils.getNotNull(overAreaPrice.getMinArea());
                //最大面积
                maxArea = BigDecimalUtils.getNotNull(overAreaPrice.getMaxArea());
                //区间面积的差值
                itemSubArea = BigDecimalUtils.getBigAndBigSub(maxArea, minArea);

                //定义面积段的key值：（在财务表中也会显示）
                String areaKey = BigDecimalUtils.getAbsolute(overAreaPrice.getMaxArea()) + "-" + BigDecimalUtils.getAbsolute(overAreaPrice.getMinArea()) + "(含)";
                //如果是最后一个面积段，key值为:  面积（以上）
                if (overAreaPriceListLength > 1) {
                    if (i == overAreaPriceListLength - 1) {
                        areaKey = BigDecimalUtils.getAbsolute(overAreaPrice.getMaxArea()) + "以上";
                    }
                }
                //定义本次面积段超出的面积以及需要花费的购房款
                BigDecimal itemAreaValue = BigDecimal.ZERO, itemMoneyValue = BigDecimal.ZERO;
                Map itemMap = Maps.newLinkedHashMap();

                //选房面积超出限量面积才去进行计算，没超出的话，全是""（后来添加，用来处理财务结算表显示问题）
                if (contract.getZzResultArea().compareTo(BigDecimal.ZERO) < 0 && contract.getZzResultAreaStatus() != null && contract.getZzResultAreaStatus() == 1) {
                    if (zzResultArea.compareTo(itemSubArea) <= 0) {
                        //如果当前选房超出面积 <= 该区间面积的差值，直接将当前超出的面积赋给本区间的面积即可
                        itemAreaValue = zzResultArea;

                        //计算需要花费的购房款（为负数：被征收人应缴纳金额）
                        itemMoneyValue = BigDecimalUtils.getBigAndBigMul(itemAreaValue, overAreaPrice.getPrice()).setScale(0, BigDecimal.ROUND_HALF_UP);

                        zzResultArea = BigDecimal.ZERO;   //该循环后，超出面积为0了
                    } else {
                        //否则，本段超出面积为：最大面积 - 最小面积
                        itemAreaValue = BigDecimalUtils.getBigAndBigSub(maxArea, minArea);
                        //计算需要花费的购房款（为负数：被征收人应缴纳金额）
                        itemMoneyValue = BigDecimalUtils.getBigAndBigMul(itemAreaValue, overAreaPrice.getPrice()).setScale(0, BigDecimal.ROUND_HALF_UP);
                        zzResultArea = BigDecimalUtils.getBigAndBigSub(zzResultArea, itemSubArea);   //该循环后超出面积应把此区间内的面积差减去，为当前还剩余超出的面积
                    }
                }

                itemMap.put("area", BigDecimalUtils.getNotNullStr(itemAreaValue));
                itemMap.put("price", BigDecimalUtils.getNotNullStr(overAreaPrice.getPrice()));
                itemMap.put("money", BigDecimalUtils.getNotNullStr(itemMoneyValue));
                resultMap.put(areaKey, itemMap);
            }
        }
        return resultMap;
    }


    /**
     * 特殊区间，该区间只使用于二个区间段，且先回购，再进行扩购
     *
     * @param contractId
     * @return
     */
    public Map<String, Map> getOverHouseMoneySpecialMap(Contract contract) {
        Map<String, Map> resultMap = Maps.newLinkedHashMap();
        if (contract == null || contract.getParameter() == null) {
            return resultMap;
        }
        List<OverAreaScPrice> OverAreaScPriceList = this.getOverAreaScPriceListByParameterId(contract.getParameter().getId());
        Precondition.checkSqdsArguement(OverAreaScPriceList.size() == 2, "数据有误，请联系技术支持！");

        if (CollectionUtils.isNotEmpty(OverAreaScPriceList)) {
            //选房超出面积，先取出选房超出的面积
            BigDecimal zzResultArea = BigDecimalUtils.getNotNull(contract.getZzResultArea());
            //定义每一个面积段的最小、最大、差值（最大-最小）
            BigDecimal minArea = BigDecimal.ZERO, maxArea = BigDecimal.ZERO, itemSubArea = BigDecimal.ZERO;
            Integer sortNum = 0;
            //定义面积段的长度
            int overAreaPriceListLength = OverAreaScPriceList.size();
            //循环每一个面积段
            for (int i = 0; i < overAreaPriceListLength; i++) {
                //取出面积段bean
                OverAreaScPrice overAreaPrice = OverAreaScPriceList.get(i);
                //最小面积
                minArea = BigDecimalUtils.getNotNull(overAreaPrice.getMinArea());
                //最大面积
                maxArea = BigDecimalUtils.getNotNull(overAreaPrice.getMaxArea());

                sortNum = IntegerUtils.getNotNull(overAreaPrice.getSortNum());

                //区间面积的差值
                itemSubArea = BigDecimalUtils.getBigAndBigSub(maxArea, minArea);
                //定义本次面积段超出的面积以及需要花费的购房款
                BigDecimal itemAreaValue = BigDecimal.ZERO, itemMoneyValue = BigDecimal.ZERO;
                Map itemMap = Maps.newLinkedHashMap();

                //定义面积段的key值：（在财务表中也会显示）
                String areaKey = "";
                if (contract.getZzResultAreaStatus() != null && contract.getZzResultAreaStatus() == 2) {
                    if (sortNum < 0) {
                        areaKey = "回购部分" + BigDecimalUtils.getAbsolute(overAreaPrice.getMaxArea()) + "-" + BigDecimalUtils.getAbsolute(overAreaPrice.getMinArea()) + "(含)";
                        //特殊区间进行计算
                        itemAreaValue = itemSubArea;
                        itemMoneyValue = BigDecimalUtils.getBigAndBigMul(itemAreaValue, overAreaPrice.getPrice()).setScale(0, BigDecimal.ROUND_HALF_UP);
                    } else if (sortNum > 0) {
                        areaKey = "扩购部分" + overAreaPrice.getMinArea() + "-" + overAreaPrice.getMaxArea() + "(含)";
                        //特殊区间进行计算
                        itemAreaValue = itemSubArea;
                        itemMoneyValue = BigDecimalUtils.getBigAndBigMul(itemAreaValue, overAreaPrice.getPrice()).setScale(0, BigDecimal.ROUND_HALF_UP).negate();
                    }
                }

                itemMap.put("area", BigDecimalUtils.getNotNullStr(itemAreaValue));
                itemMap.put("price", BigDecimalUtils.getNotNullStr(overAreaPrice.getPrice()));
                itemMap.put("money", BigDecimalUtils.getNotNullStr(itemMoneyValue));
                resultMap.put(areaKey, itemMap);
            }
        }
        return resultMap;
    }
}
